#include "../Device/led.h"

#include <string.h>

#include "../BSP/rand.h"
#include "main.h"

#ifdef DEBUG
uint8_t data[DATA_SIZE];
LED_Leaf_Mode_t leaf_mode[LEAF_NUMBER];
uint8_t active_leaf_number = 0;
uint8_t number = LEAF_NUMBER;
#else
static uint8_t data[DATA_SIZE];
static LED_Leaf_Mode_t leaf_mode[LEAF_NUMBER + 1];
static uint8_t active_leaf_number = 0;
static uint8_t number = LEAF_NUMBER;
#endif

/* 一个灯珠的颜色对应数组 */
static const uint8_t OFF[24] = {
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};

static const uint8_t RED[24] = {
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
};

static const uint8_t BLUE[24] = {
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
};

static const uint8_t* COLOR = NULL;

extern uint32_t system_time_s;
extern uint32_t system_time_ms;

void LED_Init() {
  BSP_Rand_Init();
  HAL_TIM_Base_Start_IT(&htim4);
  if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0))
    COLOR = RED;
  else
    COLOR = BLUE;
  memset(data, 0, DATA_SIZE);
  LED_PackData(LEAF_SWORD);
  BSP_PWM_Start(&htim1, TIM_CHANNEL_1, (uint32_t*)data, DATA_SIZE);
  LED_EnableOneLeaf();
}

void LED_PackData(LED_Leaf_Mode_t mode) {
  uint8_t* tmp = data + 20 * 4;

  switch (mode) {
    case LEAF_OFF:
      for (uint16_t i = 0; i < LED_NUMBER; i++) {
        memcpy(tmp + 24 * i, OFF, 24);
      }
      break;
    case LEAF_HAMMER:
      /* 第二部分 */
      for (uint16_t i = SECOND_NUMBER / 2; i < SECOND_NUMBER; i++) {
        for (uint16_t t = 0; t < SECOND_LENTH; t++) {
          if ((i + t + (system_time_ms / 500) * 2 + 2) / 2 % 2) {
            memcpy(tmp + (i * SECOND_LENTH + t) * 24, COLOR, 24);
          } else {
            memcpy(tmp + (i * SECOND_LENTH + t) * 24, OFF, 24);
          }
        }
      }
      for (uint16_t i = 0; i < SECOND_NUMBER / 2; i++) {
        memcpy(tmp + i * SECOND_LENTH * 24,
               tmp + (SECOND_NUMBER - i - 1) * SECOND_LENTH * 24,
               24 * SECOND_LENTH);
      }
      /* 第三部分 */
      tmp += SECOND_NUMBER * SECOND_LENTH * 24;
      for (uint16_t i = 0; i < THIRD_LENTH; i++) {
        memcpy(tmp + i * 24, OFF, 24);
      }
      /* 第一部分 */
      tmp += THIRD_LENTH * 24;
      for (uint16_t i = 0; i < 2 * (FIRST_HEIGHT + FIRST_WIDTH); i++) {
        memcpy(tmp + i * 24, COLOR, 24);
      }
      break;
    case LEAF_SWORD:
      for (uint16_t i = 0; i < LED_NUMBER; i++) {
        memcpy(tmp + 24 * i, COLOR, 24);
      }
      break;
  }
}

void LED_Update(bool test) {
  static LED_Leaf_Name_t leaf = LEAF_2_2;
  if (test)
    LED_PackData(LEAF_SWORD);
  else
    LED_PackData(leaf_mode[leaf]);
  switch (leaf) {
    case LEAF_2_2:
      BSP_PWM_Start(&htim2, TIM_CHANNEL_2, (uint32_t*)data, DATA_SIZE);
      break;
    case LEAF_2_3:
      BSP_PWM_Start(&htim2, TIM_CHANNEL_3, (uint32_t*)data, DATA_SIZE);
      break;
    case LEAF_2_4:
      BSP_PWM_Start(&htim2, TIM_CHANNEL_4, (uint32_t*)data, DATA_SIZE);
      break;
    case LEAF_3_1:
      BSP_PWM_Start(&htim3, TIM_CHANNEL_1, (uint32_t*)data, DATA_SIZE);
      break;
    case LEAF_3_4:
      BSP_PWM_Start(&htim3, TIM_CHANNEL_4, (uint32_t*)data, DATA_SIZE);
      break;
    default:
      return;
  }
  if (leaf < LEAF_3_4)
    leaf++;
  else
    leaf = LEAF_2_2;
}

void LED_EnableOneLeaf() {
  leaf_mode[number] = LEAF_SWORD;
  if (active_leaf_number >= LEAF_NUMBER) return;
  number = BSP_Rand_Get(LEAF_NUMBER);
  while (leaf_mode[number] != LEAF_OFF) {
    number = (++number) % LEAF_NUMBER;
  }
  leaf_mode[number] = LEAF_HAMMER;
  active_leaf_number++;
}

void LED_Reset() {
  memset(leaf_mode, LEAF_OFF, LEAF_NUMBER * sizeof(LED_Leaf_Mode_t));
  number = LEAF_NUMBER;
  active_leaf_number = 0;
  LED_EnableOneLeaf();
}

bool LED_CheckLeaf(LED_Leaf_Name_t name) {
  return leaf_mode[name] == LEAF_HAMMER;
}
